package com.example.zhang.service;

import com.example.zhang.dto.*;
import com.example.zhang.mapper.CabinetMapper;
import com.example.zhang.util.SerialPortUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

@Service
public class CabinetServiceImpl implements CabinetService {
    @Autowired
    private CabinetMapper cabinetMapper;
    
    private ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public CabinetStatusResponse getCabinetStatus() {
        // 查询终端状态
        Map<String, Object> parsed = SerialPortUtil.queryAndUpdateDbWithRetry(cabinetMapper);
        if (parsed == null) {
            // 如果查询失败，
            return new CabinetStatusResponse();
        }
        
        CabinetStatusResponse resp = new CabinetStatusResponse();
        resp.setCode(0);
        resp.setCurrentTemp(parsed.get("currentTemp") == null ? 0 : ((Number)parsed.get("currentTemp")).doubleValue());
        resp.setSetTemp(parsed.get("setTemp") == null ? 0 : ((Number)parsed.get("setTemp")).doubleValue());
        resp.setCompressorStatus(parsed.get("compressorStatus") == null ? 0 : ((Number)parsed.get("compressorStatus")).intValue());
        // 设备地址赋值（直接用Integer）
        Object deviceAddrObj = parsed.get("deviceAddr");
        if (deviceAddrObj != null) {
            if (deviceAddrObj instanceof Integer) {
                resp.setDeviceAddr((Integer) deviceAddrObj);
            } else {
                try {
                    resp.setDeviceAddr(Integer.parseInt(deviceAddrObj.toString()));
                } catch (Exception e) {
                    resp.setDeviceAddr(0); // 默认值
                }
            }
        }
        
        // 处理抽屉状态
        try {
            @SuppressWarnings("unchecked")
            List<Integer> drawers = (List<Integer>)parsed.get("lockStates");
            if (drawers == null || drawers.isEmpty()) {
                drawers = List.of(0,0,0,0,0,0,0,0,0,0);
            }
            resp.setDrawers(drawers);
        } catch (Exception e) {
            resp.setDrawers(List.of(0,0,0,0,0,0,0,0,0,0));
        }
        
        // 新增：采集时间间隔T2和压缩机启动时延T3
        if (parsed.get("uploadIntervalT2") != null) {
            resp.setUploadIntervalT2(((Number)parsed.get("uploadIntervalT2")).intValue());
        }
        if (parsed.get("compressorDelayT3") != null) {
            resp.setCompressorDelayT3(((Number)parsed.get("compressorDelayT3")).intValue());
        }
        
        // 新增：设备ID
        if (parsed.get("deviceId") != null) {
            resp.setDeviceId(parsed.get("deviceId").toString());
        }
        
        // 温度控制偏差
        if (parsed.get("tempDeviation") != null) {
            resp.setTempDeviation(((Number)parsed.get("tempDeviation")).intValue());
        }
        
        return resp;
    }

    @Override
    public BaseResponse switchDrawer(DrawerSwitchRequest request) {
        int drawerId = request.getDrawerId();
        String action = request.getAction();
        boolean ok = false;
        List<Integer> currentDrawers = null;
        try {
            Map<String, Object> currentStatus = cabinetMapper.selectCabinetStatus();
            String currentDrawerStatusJson = (String)currentStatus.get("drawers");
            currentDrawers = objectMapper.readValue(currentDrawerStatusJson, new TypeReference<List<Integer>>() {});
        } catch (Exception e) {
            currentDrawers = List.of(0,0,0,0,0,0,0,0,0,0);
        }
        int drawerIndex = drawerId - 1;
        if (drawerIndex >= 0 && drawerIndex < currentDrawers.size()) {
            currentDrawers.set(drawerIndex, "ON".equalsIgnoreCase(action) ? 1 : 0);
        }
        int controlBits = 0;
        for (int i = 0; i < 10; i++) {
            if (currentDrawers.get(i) == 1) {
                controlBits |= (1 << i);
            }
        }
        for (int i = 0; i < 3; i++) {
            byte[] unlockFrame = com.example.zhang.util.ProtocolUtil.buildUnlockFrame((byte)0x01, (byte)0x01, controlBits);
            
            try {
                SerialPortUtil.send(unlockFrame);
                Thread.sleep(500);
            } catch (Exception e) {
                Thread.currentThread().interrupt();
            }
            Map<String, Object> status = SerialPortUtil.queryAndUpdateDbWithRetry(cabinetMapper);
            if (status != null && status.get("lockStates") != null) {
                @SuppressWarnings("unchecked")
                List<Integer> drawers = (List<Integer>)status.get("lockStates");
                if (drawers.size() == 10 && drawers.get(drawerIndex).equals(currentDrawers.get(drawerIndex))) {
                    ok = true;
                    break;
                }
            }
        }
        if (ok) {
            try {
                String newDrawerStatusJson = objectMapper.writeValueAsString(currentDrawers);
                cabinetMapper.updateDrawerStatus(newDrawerStatusJson);
            } catch (Exception e) {
                // ignore
            }
        }
        BaseResponse response = new BaseResponse();
        if (ok) {
            response.setCode(0);
            response.setMessage("抽屉" + drawerId + ("ON".equalsIgnoreCase(action) ? "已打开" : "已关闭"));
        } else {
            response.setCode(1);
            response.setMessage("抽屉控制失败，设备未响应或状态不一致");
        }
        return response;
    }

    @Override
    public BaseResponse tempControl(TempControlRequest request) {
        String action = request.getAction();
        int expectStatus = 0;
        if ("ON".equalsIgnoreCase(action)) {
            expectStatus = 1;
        } else if ("OFF".equalsIgnoreCase(action)) {
            expectStatus = 0;
        } else if ("ERROR".equalsIgnoreCase(action)) {
            expectStatus = 3;
        } else {
            BaseResponse response = new BaseResponse();
            response.setCode(1);
            response.setMessage("未知指令");
            return response;
        }
        boolean ok = false;
        for (int i = 0; i < 3; i++) {
            SerialPortUtil.sendCompressorCommand(expectStatus);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            Map<String, Object> status = SerialPortUtil.queryAndUpdateDbWithRetry(cabinetMapper);
            if (status != null && status.get("compressorStatus") != null) {
                int actual = ((Number)status.get("compressorStatus")).intValue();
                if (actual == expectStatus) {
                    ok = true;
                    break;
                }
            }
        }
        if (ok) {
            cabinetMapper.updateCompressorStatus(expectStatus);
        }
        BaseResponse response = new BaseResponse();
        if (ok) {
            response.setCode(0);
            if ("ON".equalsIgnoreCase(action)) {
                response.setMessage("温控状态已更新为: 预启动，稍后自动运行");
            } else if ("OFF".equalsIgnoreCase(action)) {
                response.setMessage("温控状态已更新为: 停止");
            } else if ("ERROR".equalsIgnoreCase(action)) {
                response.setMessage("温控状态已更新为: 故障");
            }
        } else {
            response.setCode(1);
            response.setMessage("压缩机控制失败，设备未响应或状态不一致");
        }
        return response;
    }

    @Override
    public BaseResponse setTemp(SetTempRequest request) {
        double value = request.getValue();
        // 获取设备地址，优先从数据库查
        int deviceAddr;
        try {
            Map<String, Object> status = cabinetMapper.selectCabinetStatus();
            if (status != null && status.get("deviceAddr") != null) {
                deviceAddr = Integer.parseInt(status.get("deviceAddr").toString());
            } else {
                deviceAddr = 1;
            }
        } catch (Exception e) {
            deviceAddr = 1;
        }
        boolean ok = false;
        for (int i = 0; i < 3; i++) {
            SerialPortUtil.sendSetTempCommand(value); // 发送设温指令
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            // 查询终端状态
            Map<String, Object> status = SerialPortUtil.queryAndUpdateDbWithRetry(cabinetMapper);
            if (status != null && status.get("setTemp") != null) {
                double actual = ((Number)status.get("setTemp")).doubleValue();
                if (actual == value) {
                    ok = true;
                    break;
                }
            }
        }
        if (ok) {
            cabinetMapper.updateSetTemp(value);
        }
        BaseResponse response = new BaseResponse();
        if (ok) {
            response.setCode(0);
            response.setMessage("设定温度已更新为: " + value + "°C");
        } else {
            response.setCode(1);
            response.setMessage("设定温度失败，设备未响应或状态不一致");
        }
        return response;
    }

    @Override
    public BaseResponse setParams(SetParamsDTO params) {
        // 1. 组装18字节参数区
        byte[] paramBytes = new byte[18];
        if (params.getDeviceId() != null) {
            String deviceId = params.getDeviceId();
            for (int i = 0; i < 5 && i * 2 + 2 <= deviceId.length(); i++) {
                paramBytes[i] = (byte) Integer.parseInt(deviceId.substring(i * 2, i * 2 + 2), 16);
            }
        }
        if (params.getDeviceAddr() != null) {
            paramBytes[5] = params.getDeviceAddr().byteValue();
        }
        paramBytes[6] = 0x00;
        if (params.getUploadIntervalT2() != null) {
            paramBytes[7] = params.getUploadIntervalT2().byteValue();
        }
        if (params.getCompressorDelayT3() != null) {
            paramBytes[8] = params.getCompressorDelayT3().byteValue();
        }
        paramBytes[9] = 0x00;
        paramBytes[10] = 0x00;
        if (params.getSetTemp() != null) {
            double setTemp = params.getSetTemp();
            paramBytes[11] = SerialPortUtil.buildTempByte(setTemp);
        }
        if (params.getTempDeviation() != null) {
            paramBytes[12] = params.getTempDeviation().byteValue();
        }
        paramBytes[13] = (byte)0xFF;
        paramBytes[14] = (byte)0xFF;
        paramBytes[15] = (byte)0xFF;
        paramBytes[16] = (byte)0xFF;
        paramBytes[17] = 0x00;
        boolean ok = false;
        for (int i = 0; i < 3; i++) {
            byte[] frame = com.example.zhang.util.ProtocolUtil.buildSetParamsFrame((byte)0x01, paramBytes[5], paramBytes);
            
            try {
                SerialPortUtil.send(frame);
                Thread.sleep(500);
            } catch (Exception e) {
                Thread.currentThread().interrupt();
            }
            Map<String, Object> status = SerialPortUtil.queryAndUpdateDbWithRetry(cabinetMapper);
            if (status == null) continue;
            boolean match = true;
            if (params.getUploadIntervalT2() != null && status.get("uploadIntervalT2") != null) {
                if (!params.getUploadIntervalT2().equals(((Number)status.get("uploadIntervalT2")).intValue())) match = false;
            }
            if (params.getCompressorDelayT3() != null && status.get("compressorDelayT3") != null) {
                if (!params.getCompressorDelayT3().equals(((Number)status.get("compressorDelayT3")).intValue())) match = false;
            }
            if (params.getSetTemp() != null && status.get("setTemp") != null) {
                double actual = ((Number)status.get("setTemp")).doubleValue();
                if (Math.abs(actual - params.getSetTemp()) > 0.5) match = false;
            }
            if (params.getTempDeviation() != null && status.get("tempDeviation") != null) {
                if (!params.getTempDeviation().equals(((Number)status.get("tempDeviation")).intValue())) match = false;
            }
            if (match) {
                ok = true;
                break;
            }
        }
        if (ok) {
            try {
                String paramsJson = objectMapper.writeValueAsString(params);
                cabinetMapper.updateParams(paramsJson);
            } catch (Exception e) {
                // ignore
            }
        }
        BaseResponse response = new BaseResponse();
        if (ok) {
            response.setCode(0);
            response.setMessage("参数设置成功");
        } else {
            response.setCode(1);
            response.setMessage("参数设置失败，设备未响应或状态不一致");
        }
        return response;
    }
} 